<!--
  @description: 自定义树状选择器
  @creator: yiming
  @date: 2021/03/11
-->
<template>
  <div
    :class="[
      'i-tree-select',
      disabled && 'disabled',
      value != undefined && 'selected-val',
    ]"
  >
    <InputLabel v-if="label" :text="label" :required="required" />
    <div :class="['ivu-tree-select', showDropdown ? 'ivu-select-visible ' : '']">
      <div class="ivu-select-selection select-input" @click="handleClickInput">
        <input
          type="text"
          v-model="inputVal"
          :placeholder="placeholder"
          v-if="filterable"
        />
        <template v-else>
          <span class="ivu-select-selected-val" v-if="inputVal">{{ inputVal }}</span>
          <span class="ivu-select-placeholder" v-else>{{ placeholder }}</span>
        </template>
        <i class="ivu-icon ivu-icon-ios-arrow-down ivu-select-arrow"></i>
        <i
          class="ivu-icon ivu-icon-ios-close-circle ivu-cascader-arrow"
          @click.stop="handleClearInput"
        ></i>
      </div>
      <transition name="dropdown">
        <div
          class="ivu-select-dropdown select-dropdown"
          v-show="showDropdown"
          v-autoHide="{ showDropdown }"
        >
          <Tree
            v-bind="$attrs"
            v-on="$listeners"
            @on-select-change="handleTreeSelect"
            :key="label"
            :data="filteredData"
          />
        </div>
      </transition>
    </div>
  </div>
</template>

<script>
import { inputMixin } from "./mixin/inputMixin";
import u from "_u";

export default {
  name: "IviewTreeSelect",
  mixins: [inputMixin],
  components: {},
  // 自定义v-model
  model: {
    prop: "value",
    event: "select",
  },
  props: {
    // 是否搜索
    filterable: {
      type: Boolean,
      default: true,
    },
    // 是否可以清除选中
    clearable: {
      type: Boolean,
      default: true,
    },
    // 劫持data
    data: {
      type: Array,
    },
    // 是否禁用
    disabled: {
      type: Boolean,
    },
    // v-model 值
    value: {
      type: [Number, String],
    },
    // 输入框标签
    label: {
      type: String,
    }, // 是否必填，传入label才有效
    required: {
      type: Boolean,
    },
    placeholder: {
      type: String,
      default: "请输入...",
    },
  },
  data() {
    return {
      // 是否显示下拉框
      showDropdown: false,
      // 输入框输入值
      inputVal: "",
      filteredData: this.$u.object.deepCopy(this.data),
    };
  },
  computed: {
    // 树状子点
    treeDict() {
      return this.$u.tree.tree2dict(this.data || [], "value");
    },
    // 显示选择的文本
    // valueTitle: {
    //   get() {
    //     let ret = "";
    //     if (this.filterable) {
    //       if (this.showDropdown) {
    //         ret = this.inputVal;
    //       } else {
    //         ret = this.treeDict[this.value] && this.treeDict[this.value].title;
    //       }
    //     } else {
    //       ret = this.treeDict[this.value] && this.treeDict[this.value].title;
    //     }
    //     return ret;
    //   },
    //   set(newVal) {
    //     // 获取到输入框当前输入的值
    //     this.inputVal = newVal;
    //   },
    // },
  },
  watch: {
    showDropdown: {
      handler(n) {
        if (this.filterable) {
          if (n) {
            this.getFilteredData();
          } else {
            // 下拉框隐藏时清空输入值
            this.inputVal = "";
          }
        }
      },
    },
    inputVal: {
      handler() {
        if (this.filterable) {
          this.getFilteredData();
        }
      },
    },
  },
  methods: {
    // 计算过滤后的值
    getFilteredData: u.tool.debounce(function () {
      let copyData = this.$u.object.deepCopy(this.data);

      if (this.inputVal === "" || this.inputVal == null) return copyData;

      // 第一次遍历，打标签
      copyData = this.$u.tree.handleTreeNode(copyData, (node, parentNode) => {
        parentNode && (node.parent = parentNode);

        // 命中关键词的节点设置matched标记
        if (node.title.includes(this.inputVal)) {
          node.matched = true; // 筛选词命中

          // 往上找父节点设置keep标志
          this.searchParent(node, (parent) => {
            parent && (parent.keep = true);
          });

          // 向下找子节点设置keep标记
          if (node.children && node.children.length) {
            this.$u.tree.handleTreeNode(node.children, (node) => {
              node.keep = true;
            });
          }

          // 这里有一个浪费，就是暂时无法阻止继续往下找子节点
        }
      });

      // 第二次遍历，删除节点
      this.filteredData = this.$u.tree.filterTree(copyData, (node) => {
        this.$set(node, "expand", true);
        return node.matched || node.keep;
      });
    }, 300),

    // 清空选择框
    handleClearInput() {
      this.inputVal = "";
      this.$emit("select", null);
    },
    // 递归往上找父节点
    searchParent(node, fn) {
      if (node.parent) {
        fn.call(null, node.parent);
        this.searchParent(node.parent, fn);
      }
    },
    // 点击选择框
    handleClickInput() {
      if (!this.disabled) {
        this.showDropdown = !this.showDropdown;
      }
    },
    // 选中节点
    handleTreeSelect(nodeArr) {
      if (nodeArr[0]) {
        let node = nodeArr[0];
        this.$emit("select", node.value || node.id);
        this.showDropdown = false;
        this.$nextTick(() => {
          this.inputVal =
            (this.treeDict[this.value] && this.treeDict[this.value].title) || "";
        });
      }
    },
  },
  created() {},
};
</script>

<style lang="less" scoped>
@import "./config/input";
.i-tree-select {
  .input-layout();
  .ivu-tree-select {
    // position: relative; /** 加了这个会有问题？？！！ */
    .ivu-icon-ios-close-circle {
      display: none;
    }
    &.ivu-select-visible {
      .select-input {
        position: relative;
        box-shadow: 0px 0px 6px 0px rgba(133, 247, 220, 0.4),
          inset 0px 0px 8px 0px rgba(0, 0, 0, 0.48);
        .border(@main-color);
      }
    }
    .select-input {
      .input-view;
      .input-width;
      .input-text;
      font-size: @base-font-size;
      line-height: @input-height;
      height: @input-height;
      width: 240px;
      padding: 0 8px;
      transition: all 0.3s;
      cursor: pointer;
      .ivu-select-placeholder {
        .placeholder();
      }
      &:hover {
        .border(@main-color);
      }
      > input {
        .input-text;
        position: absolute;
        left: 0;
        width: 100%;
        height: 100%;
        padding-left: 8px;
        // .border;
        border: none;
        .bg(transparent);
        &:focus {
          outline: none;
        }
      }
    }
    .select-dropdown {
      .select-dropdown;
      .input-show-scroll;
      min-width: 240px;
      position: absolute;
      // top: 40px;
      // left: 0;
      z-index: 900;
      /deep/.ivu-tree {
        padding: 0 20px 0 10px;
        li {
          // margin: 0;
          .ivu-tree-arrow {
            display: inline-block;
            line-height: 34px;
            height: 34px;
            .ivu-icon {
              color: #d3d6d9;
            }
          }
          .ivu-tree-title {
            padding: 0 40px 0 10px;
            display: inline-block;
            font-size: 16px;
            width: 100%;
            line-height: 34px;
            height: 34px;
            color: #d3d6d9;
            .click-active;
            user-select: none;
            transition: all 0.3s;
            &:hover {
              .bg(fade(#3a3a3a, 80%));
            }
            &.ivu-tree-title-selected {
              .bg(fade(#3a3a3a, 80%));
              pointer-events: none;
            }
          }
        }
      }
    }
  }
  &.disabled {
    .ivu-tree-select {
      .select-input,
      .select-input:hover {
        cursor: not-allowed;
        opacity: 0.5;
        border: 1px solid #4e4e4f;
        box-shadow: inset 0 0 8px 0 rgba(0, 0, 0, 0.48);
      }
    }
  }
  &.selected-val {
    &:hover {
      .ivu-icon-ios-arrow-down {
        display: none;
      }
      .ivu-icon-ios-close-circle {
        display: inline-block;
      }
    }
  }
}
</style>
